package de.bazinga.rotw.player;

import com.jme.bounding.BoundingBox;
import com.jme.math.Vector3f;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Box;
import com.jmex.game.state.GameStateManager;
import com.jmex.jbullet.PhysicsSpace;
import com.jmex.jbullet.collision.shapes.CollisionShape;
import com.jmex.jbullet.nodes.PhysicsCharacterNode;

import de.bazinga.rotw.game.Game;
import de.bazinga.rotw.game.RotwGameState;
import de.bazinga.rotw.game.TextCache;
import de.bazinga.rotw.person.Person;
import de.bazinga.rotw.sound.Sound;
import de.bazinga.rotw.statistics.OnlineStatistics;
import de.bazinga.rotw.util.GlobalSettings;

public class Player extends Person {
	private static final long serialVersionUID = 1L;

	
	/**
	 * Contains the PhysicsBody
	 * PhysicsNode for usual Persons
	 * PhysicsCharacterNode for Players
	 */
	protected PhysicsCharacterNode physicsPersonNode = null;
	
	private Box feet = null;
	
	
	private long lastAmmo = 0;
	private long lastArmor = 0;
	
	private PlayerActions playerActions = null;
	
	private long lastHitSound = 0;
	
	public Player() {
		super("Player","blue",Person.TEAM_ONE);
		
		Game.getGame().getCamera().setLocation(this.getWorldTranslation());
		
		// Add small box to check if he touches the ground
		feet = new Box("playerfeet",new Vector3f(-0.1f,-0.1f,-0.1f),new Vector3f(0.1f,0.7f,0.1f));
		feet.setModelBound(new BoundingBox());
		feet.updateModelBound();
		
		// Hide Feet
		feet.setCullHint(Spatial.CullHint.Always);
		
		feet.setRandomColors();

		getBody().attachChild(feet);
		
		this.attachChild(feet);

		// Hide the Model
		this.setCullHint(Spatial.CullHint.Always);
		
		

        teamBox.setCullHint(CullHint.Never);

        
        
        //BoxCollisionShape collShape = new BoxCollisionShape((BoundingBox)this.getWorldBound());
        physicsPersonNode = new PhysicsCharacterNode(this, CollisionShape.ShapeTypes.SPHERE,0.1f);
        physicsPersonNode.setLocalScale(0.24f);
        physicsPersonNode.getCharacterController().setGravity(GlobalSettings.GRAVITY);
        physicsPersonNode.getCharacterController().setJumpSpeed(GlobalSettings.JUMPYSPEED);
       // physicsPersonNode.attachChild(this);
        //physicsPersonNode.updateRenderState();
        PhysicsSpace.getPhysicsSpace().add(physicsPersonNode);

		//this.setLocalTranslation(new Vector3f(0,0,0));
	}
	
	public void setLocalTranslation(Vector3f trans) {
		physicsPersonNode.setLocalTranslation(trans.x, trans.y, trans.z);
	}
	
	public Vector3f getLocalTranslation() {
		if(physicsPersonNode != null)
			return physicsPersonNode.getLocalTranslation();
		
		return Vector3f.ZERO;
	}
	
	/**
	 * Reset everything (update health/ammo/armor and set to start)
	 */
	public void reset(boolean resetScore) {
		super.reset(resetScore);
		
		// Hide Player again
		this.setCullHint(Spatial.CullHint.Always);
		
		
		//playerActions.setFalling(false);
		playerActions.reset();
		
		TextCache.getInstance().getTextfield("score").setText("Score: "+getScore());
	
		this.refillAmmo();
		
		updateHealthText();
		TextCache.getInstance().getTextfield("armor").setText("Armor: "+getArmor());
		updateAmmoText();

		((RotwGameState)GameStateManager.getInstance().getChild("gameState")).updateWeaponIcon();
		
	}
	
	
	
	/**
	 * Get the Camera-Position
	 * @return position of the Camera
	 */
	public Vector3f getCameraPosition() {
		Vector3f camPos = super.getCameraPosition();
		
		
		/*if(playerActions.isInWater()) {
			return new Vector3f(this.getLocalTranslation().x,
					this.getLocalTranslation().y  + 3.5f,
					this.getLocalTranslation().z);
		}*/
		return camPos;
	}

	
	
	/**
	 * Refill the Ammo
	 */
	public void refillAmmo() {
		super.refillAmmo();
		
		if(Game.getGame().getSettings().isSFX() && (System.currentTimeMillis() - lastAmmo) > 1000) {
			Sound.getInstance().getAudioTrack("sounds/reload.wav").setWorldPosition(this.getWorldTranslation());
			Sound.getInstance().getAudioTrack("sounds/reload.wav").play();
			lastAmmo = System.currentTimeMillis();
		}
		updateAmmoText();
	}

	
	/**
	 * Increase the Health, play sound and update Text
	 */
	public boolean increaseHealth() {
		if(super.increaseHealth()) {
		
			if(Game.getGame().getSettings().isSFX()) {
				Sound.getInstance().getAudioTrack("sounds/harp.wav").setWorldPosition(this.getWorldTranslation());
				Sound.getInstance().getAudioTrack("sounds/harp.wav").play();
			}
			
			updateHealthText();
			return true;
		}
		return false;
	}
	
	
	public void setFullArmor() {
		super.setFullArmor();
		
		if(Game.getGame().getSettings().isSFX() && (System.currentTimeMillis() - lastArmor) > 1000) {
			Sound.getInstance().getAudioTrack("sounds/armour.wav").setWorldPosition(this.getWorldTranslation());
			Sound.getInstance().getAudioTrack("sounds/armour.wav").play();
			lastArmor = System.currentTimeMillis();
		}
		
		
		TextCache.getInstance().getTextfield("armor").setText("Armor: "+getArmor());
	}
	
	
	public void updateAmmoText() {
		TextCache.getInstance().getTextfield("ammo").setText("Ammunition: "+getAmmo());		
		TextCache.getInstance().getTextfield("magazine").setText("Magazines: "+getCurrentWeapon().getMagazines());		
	}
	
	
	

	
	/**
	 * Gets called by a Weapon if you fired
	 */
	public void fired() {
		super.fired();
		getCurrentWeapon().playerFired();
		updateAmmoText();
	}
	
	
	
	
	
	/**
	 * Player killed a Opponent
	 * @param opp the opponent you killed
	 */
	public void killedOpponent(String oppName) {
		super.killedOpponent(oppName);
		TextCache.getInstance().getTextfield("score").setText("Score: "+getScore());
		
		((RotwGameState)GameStateManager.getInstance().getChild("gameState")).addChatMessage("You killed "+oppName);
	}
	
	

	/**
	 * Damage done by falling
	 * @param distance the distance you fell
	 */
	public void fallDamage(float distance) {
		super.fallDamage(distance);
		
		// Only play Sound if you didnt die
		if(distance <= 25 && Game.getGame().getSettings().isSFX()) {
			Sound.getInstance().getAudioTrack("sounds/falldamage.wav").setWorldPosition(this.getWorldTranslation());
			Sound.getInstance().getAudioTrack("sounds/falldamage.wav").play();
		}
		updateHealthText();
	}
	
	
	/**
	 * Got hit
	 * @return
	 */
	public void hit(Person player, int damage) {
		super.hit(player,damage);
		
		if(Game.getGame().getSettings().isSFX() && (System.currentTimeMillis() - lastHitSound) > 1000) {
			Sound.getInstance().getAudioTrack("sounds/hit.wav").play();
			lastHitSound = System.currentTimeMillis();
		}
		
		TextCache.getInstance().getTextfield("armor").setText("Armor: "+getArmor());
		updateHealthText();
	}


	
	/**
	 * Overwrite diedFalling() so we can change the Info-Text
	 */
	public void diedFalling() {
		super.diedFalling();
		
		// Show the Player again
		this.setCullHint(Spatial.CullHint.Never);

		// Play Sound
		if(Game.getGame().getSettings().isSFX()) {
			Sound.getInstance().getAudioTrack("sounds/scream.wav").setWorldPosition(this.getWorldTranslation());
			Sound.getInstance().getAudioTrack("sounds/scream.wav").play();
		}
		
		// Set Info-Message
		((RotwGameState)GameStateManager.getInstance().getChild("gameState")).addChatMessage("You killed yourself!");
	}
	
	
	/**
	 * Overwrite died() so we can change the Info-Text
	 * @param playerName the name of the player that killed us
	 */
	public void died(String playerName, Vector3f playerLocation) {
		super.died(playerName, playerLocation);
		
		// Show the Player again
		this.setCullHint(Spatial.CullHint.Never);

		// Play Sound
		if(Game.getGame().getSettings().isSFX()) {
			Sound.getInstance().getAudioTrack("sounds/scream.wav").setWorldPosition(this.getWorldTranslation());
			Sound.getInstance().getAudioTrack("sounds/scream.wav").play();
		}
		
		// Set Info-Message
		((RotwGameState)GameStateManager.getInstance().getChild("gameState")).addChatMessage(playerName+" killed you!");
		
		// Set the camera to the opponent
		Game.getGame().getCamera().setLocation(playerLocation);
	}
	

	/**
	 * Overwrite
	 */
	public void setHealth(int health) {
		super.setHealth(health);
		
		updateHealthText();
	}

	
	
	public Box getFeet() {
		return feet;
	}
	
	public int getAmmo() {
		if(getCurrentWeapon() != null) 
			return getCurrentWeapon().getAmmo();
		
		return 0;
	}
	
	
	

	public PlayerActions getPlayerActions() {
		return playerActions;
	}


	public void setPlayerActions(PlayerActions playerActions) {
		this.playerActions = playerActions;
	}
	
	
	
	
	public void nextWeapon() {
		super.nextWeapon();
		updateAmmoText();
		((RotwGameState)GameStateManager.getInstance().getChild("gameState")).updateWeaponIcon();
	}
	
	public void previousWeapon() {
		super.previousWeapon();
		updateAmmoText();
		((RotwGameState)GameStateManager.getInstance().getChild("gameState")).updateWeaponIcon();
	}
	
	public void setWeapon(int index) {
		super.setWeapon(index);
		updateAmmoText();
		((RotwGameState)GameStateManager.getInstance().getChild("gameState")).updateWeaponIcon();
	}
	
	
	
	public void killedZombie() {
		super.killedZombie();
		OnlineStatistics.updateZombiesKilled++;
		TextCache.getInstance().getTextfield("score").setText("Score: "+getScore());
	}

	
	public void foundAllTreasures() {
		super.foundAllTreasures();
		TextCache.getInstance().getTextfield("score").setText("Score123: "+getScore());
	}
	
	
	public void increaseScore() {
		super.increaseScore();
		OnlineStatistics.updateScore++;
	}
	
	public void decreaseScore() {
		super.decreaseScore();

		OnlineStatistics.updateScore--;
	}
	
	
	public void updateDoubleDamageTime() {
		super.updateDoubleDamageTime();
		
		if(Game.getGame().getSettings().isSFX()) {
			Sound.getInstance().getAudioTrack("sounds/doubledamage.wav").play();
		}
	}
	
	

	
	public void updateHealthText() {
		if(health < 0) TextCache.getInstance().getTextfield("health").setText("Health: 0");
		else TextCache.getInstance().getTextfield("health").setText("Health: "+getHealth());	
	}

	
	

	public PhysicsCharacterNode getPhysicsNode() {
		return physicsPersonNode;
	}


	public void setPhysicsPersonNode(PhysicsCharacterNode physicsPersonNode) {
		this.physicsPersonNode = physicsPersonNode;
	}
}